package edu.fight.utils.jwt;

import edu.fight.dto.JwtUser;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Calendar;
import java.util.Date;

@Component
public class JwtUtils {



    public static Date getExpiration(){
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.MINUTE,expireTime);
//        instance.add(Calendar.SECOND,10);
        Date time = instance.getTime();
        return time;
    }

    /**
     * 私钥加密token
     *
     * @param JwtUser      载荷中的数据
     * @param privateKey    私钥
     * @return
     * @throws Exception
     */
    public static String generateToken(JwtUser JwtUser, PrivateKey privateKey) throws Exception {

        return Jwts.builder()
                .claim(JwtConstant.JWT_KEY_ID.toString(), JwtUser.getId())
                .claim(JwtConstant.JWT_KEY_USER_NAME.toString(), JwtUser.getUsername())
                .setExpiration(getExpiration())
                .signWith(SignatureAlgorithm.RS256, privateKey)
                .compact();
    }

    /**
     * 私钥加密token
     *
     * @param JwtUser      载荷中的数据
     * @param privateKey    私钥字节数组
     * @return
     * @throws Exception
     */
    public static String generateToken(JwtUser JwtUser, byte[] privateKey) throws Exception {
        return Jwts.builder()
                .claim(JwtConstant.JWT_KEY_ID.toString(), JwtUser.getId())
                .claim(JwtConstant.JWT_KEY_USER_NAME.toString(), JwtUser.getUsername())
                .setExpiration(getExpiration())
                .signWith(SignatureAlgorithm.RS256, RsaUtils.getPrivateKey(privateKey))
                .compact();
    }

    /**
     * 公钥解析token
     *
     * @param token     用户请求中的token
     * @param publicKey 公钥
     * @return
     * @throws Exception
     */
    private static Jws<Claims> parserToken(String token, PublicKey publicKey) {
        return Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token);
    }

    /**
     * 公钥解析token
     *
     * @param token     用户请求中的token
     * @param publicKey 公钥字节数组
     * @return
     * @throws Exception
     */
    private static Jws<Claims> parserToken(String token, byte[] publicKey) throws Exception {
        return Jwts.parser().setSigningKey(RsaUtils.getPublicKey(publicKey))
                .parseClaimsJws(token);
    }

    /**
     * 获取token中的用户信息
     *
     * @param token     用户请求中的令牌
     * @param publicKey 公钥
     * @return 用户信息
     * @throws Exception
     */
    public static JwtUser getInfoFromToken(String token, PublicKey publicKey) throws Exception {
        Jws<Claims> claimsJws = parserToken(token, publicKey);
        Claims body = claimsJws.getBody();
        Integer userid = (Integer) body.get(JwtConstant.JWT_KEY_ID.toString());
        String username = (String) body.get(JwtConstant.JWT_KEY_USER_NAME.toString());
        return new JwtUser( userid , username);
    }

    /**
     * 获取token中的用户信息
     *
     * @param token     用户请求中的令牌
     * @param publicKey 公钥
     * @return 用户信息
     * @throws Exception
     */
    public static JwtUser getInfoFromToken(String token, byte[] publicKey) throws Exception {
        Jws<Claims> claimsJws = parserToken(token, publicKey);
        Claims body = claimsJws.getBody();
        Integer userid = (Integer) body.get(JwtConstant.JWT_KEY_ID.toString());
        String username = (String) body.get(JwtConstant.JWT_KEY_USER_NAME.toString());
        return new JwtUser( userid , username);
    }


    /**
     * 注意，静态变量的注入
     */

    private static String salt;
    private static String privateKeyPath;
    private static String publicKeyPath;
    private static Integer expireTime;


    @Value("${jwt.salt}")
    public void setSalt(String salt) {
        JwtUtils.salt = salt;
    }

    @Value("${jwt.private-key-path}")
    public void setPrivateKeyPath(String privateKeyPath) {
        JwtUtils.privateKeyPath = privateKeyPath;
    }

    @Value("${jwt.public-key-path}")
    public void setPublicKeyPath(String publicKeyPath) {
        JwtUtils.publicKeyPath = publicKeyPath;
    }

    @Value("${jwt.expire-time}")
    public void setExpireTime(Integer expireTime) {
        JwtUtils.expireTime = expireTime;
    }

    public static String getSalt() {
        return salt;
    }

    public static String getPrivateKeyPath() {
        return privateKeyPath;
    }

    public static String getPublicKeyPath() {
        return publicKeyPath;
    }

    public static Integer getExpireTime() {
        return expireTime;
    }
}